<?php

	class Sitemap
	{
		public $user_agent = "Mozilla/4.0 Sitemap";
		
		protected $unchecked = Array();
		protected $checked = Array();
		
		protected $xml = null;
		
		public function start( $delay = 3 )
		{
			// loop until no more URLs can be found
			while( $check_url = $this->nextUrl() )
			{
				echo "Checking $check_url\n";
				
				$result = $this->getUrl( $check_url );
				
				$this->addCheckedURL( $check_url );
				
				$dom = new DOMDocument();
				
				@$dom->loadHTML( $result["html"] );
					
				if ( $result["status"] == 200 )
				{
					if ( $result["type"] == "text/html" )
						$this->addURL( $check_url, $result["filetime"], "monthly" );
					else
						continue;  // not html - move on
				}
				
				$xpath = new DOMXPath( $dom );
				$hrefs = $xpath->evaluate( "//*[@href]" );
				
				for ( $i = 0; $i < $hrefs->length; $i++ ) 
				{
					$href = $hrefs->item($i);
					
					$url = $href->getAttribute('href');
					
					$url = $this->makeAbsoluteUrl( $url, $result["base_url"] );
					
					if ( $url = $this->filterExternalURL( $url, $check_url ) )
						$this->addToQueue( $url );
				}
				
				$hrefs = $xpath->evaluate( "//*[@src]" );
				
				for ( $i = 0; $i < $hrefs->length; $i++ ) 
				{
					$href = $hrefs->item($i);
					
					$url = $href->getAttribute('src');
					
					$url = $this->makeAbsoluteUrl( $url, $result["base_url"] );
					
					if ( $url = $this->filterExternalURL( $url, $check_url ) )
						$this->addToQueue( $url );
				}
			}
		}
		
		public function getURL( $url )
		{
			$curl = curl_init();
			
			curl_setopt( $curl, CURLOPT_URL, $url );
			curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
			curl_setopt( $curl, CURLOPT_FILETIME, true );
			curl_setopt( $curl, CURLOPT_TIMEOUT, 5 );
			curl_setopt( $curl, CURLOPT_CONNECT_TIMEOUT, 5 );
			curl_setopt( $curl, CURLOPT_FOLLOWLOCATION, true );
			curl_setopt( $curl, CURLOPT_USERAGENT, $this->user_agent );
			
			$result   = curl_exec( $curl );
			
			$status   = curl_getinfo( $curl, CURLINFO_HTTP_CODE );
			$filetime = curl_getinfo( $curl, CURLINFO_FILETIME );
			$base_url = curl_getinfo( $curl, CURLINFO_EFFECTIVE_URL );
			$type     = curl_getinfo( $curl, CURLINFO_CONTENT_TYPE );
			
			curl_close( $curl );
			
			if ( $result )
				return Array(
					"html" => $result,
					"status" => $status,
					"filetime" => $filetime,
					"type" => $type,
					"base_url" => $base_url
				);
			
			// something went wrong...
			return false;
		}
		
		public function addURL( $url, $lastmod, $changefreq = false, $priority = false )
		{
			$this->urls[] = Array(
				"url" => $url,
				"filetime" => $lastmod,
				"changefreq" => $changefreq,
				"priority" => $priority
				);
		}
		
		public function addToQueue( $url )
		{
			if ( $this->checked[ strtolower( $url ) ] )
				return false;
			
			if ( $this->unchecked[ strtolower( $url ) ] )
				return true;
			
			echo "Adding $url to queue\n";
			
			$this->unchecked[ strtolower( $url ) ] = $url;
			
			return true;
		}
		
		public function addCheckedURL( $url )
		{
			$this->checked[ strtolower( $url ) ] = $url;
			
			return true;
		}
		
		public function nextUrl()
		{
			return array_shift( $this->unchecked );
		}
		
		public function save( $file = false )
		{
			$sitemap_xml = simplexml_load_string( '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.google.com/schemas/sitemap/0.84" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.google.com/schemas/sitemap/0.84 http://www.google.com/schemas/sitemap/0.84/sitemap.xsd" />' );
			
			$urls =& $sitemap_xml->urlset;
			
			foreach( $this->urls AS $record )
			{
				// We are now able to manipulate the object ($go) and add a new url child element to it.
				$sitemap = $urls->addChild('url');
		
				// Now we create are four child elements.
				$sitemap->addChild( 'loc', $record["url"] );
				
				if ( $record["priority"] )
					$sitemap->addChild( 'priority', $record["priority"] );
		
				if ( $record["filetime"] )
					$sitemap->addChild( 'lastmod', ( $record["filetime"] == "-1" ? date("Y-m-d") : date("Y-m-d", $record["filetime"] ) ) );
				
				if ( $record["changefreq"] )
					$sitemap->addChild( 'changefreq', $record["changefreq"] );
			}
			
			$dom = new DomDocument;
			$dom->loadXML( $sitemap_xml->asXML() );
			$dom->formatOutput = true;
			
			return $dom->saveXML();
		}
		
		public function load( $file )
		{
			if ( $this->xml = simplexml_load_file( $file ) )
			{
				
				
				return true;
			}
			
			return false;
		}
		
		public function makeAbsoluteUrl( $url, $base_url )
		{
			$url_parts      = parse_url( $url );
			$base_url_parts = parse_url( $base_url );
			
			if ( $url_parts["scheme"] )
				return $url;
			
			if ( substr( $url, 0, 1 ) == "/" )
				return $base_url_parts["scheme"] ."://". $base_url_parts["host"] . $url;
			
			print_r($base_url_parts);
			
			return $base_url_parts["scheme"] ."://". 
				   $base_url_parts["host"] . 
				   ( eregi( "/", $base_url_parts["path"] ) ? substr($base_url_parts["path"], 0, strrpos($base_url_parts["path"],"/") ) : "" ) . 
				   "/" . $url;
		}
		
		public function filterExternalURL( $url, $base_url )
		{
			$new_url = parse_url( $url );
			$cur_url = parse_url( $base_url );
			
			if ( preg_replace( "|^(www\.)|i", "", strtolower( $new_url["host"] ) ) == preg_replace( "|^(www\.)|i", "", strtolower( $cur_url["host"] ) ) )
				return $url;
		}
	}

?>
